﻿using System;
using System.Collections;
using GeoAPI.Geometries;
using YJKGridTopologyCal.Algorithm;
using YJKGridTopologyCal.GeometriesGraph;
using YJKGridTopologyCal.Index.Sweepline;
using YJKGridTopologyCal.Utilities;

namespace YJKGridTopologyCal.Operation.Valid
{
	public class SweeplineNestedRingTester
	{
		public SweeplineNestedRingTester(GeometryGraph graph)
		{
			this.graph = graph;
		}

		public Coordinate NestedPoint
		{
			get
			{
				return this.nestedPt;
			}
		}

		public void Add(ILinearRing ring)
		{
			this.rings.Add(ring);
		}

		public bool IsNonNested()
		{
			this.BuildIndex();
			SweeplineNestedRingTester.OverlapAction overlapAction = new SweeplineNestedRingTester.OverlapAction(this);
			this.sweepLine.ComputeOverlaps(overlapAction);
			return overlapAction.IsNonNested;
		}

		private void BuildIndex()
		{
			this.sweepLine = new SweepLineIndex();
			for (int i = 0; i < this.rings.Count; i++)
			{
				ILinearRing linearRing = (ILinearRing)this.rings[i];
				Envelope envelopeInternal = linearRing.EnvelopeInternal;
				SweepLineInterval sweepInt = new SweepLineInterval(envelopeInternal.MinX, envelopeInternal.MaxX, linearRing);
				this.sweepLine.Add(sweepInt);
			}
		}

		private bool IsInside(ILinearRing innerRing, ILinearRing searchRing)
		{
			Coordinate[] coordinates = innerRing.Coordinates;
			Coordinate[] coordinates2 = searchRing.Coordinates;
			if (!innerRing.EnvelopeInternal.Intersects(searchRing.EnvelopeInternal))
			{
				return false;
			}
			Coordinate coordinate = IsValidOp.FindPointNotNode(coordinates, searchRing, this.graph);
			Assert.IsTrue(coordinate != null, "Unable to find a ring point not a node of the search ring");
			if (CGAlgorithms.IsPointInRing(coordinate, coordinates2))
			{
				this.nestedPt = coordinate;
				return true;
			}
			return false;
		}

		private readonly GeometryGraph graph;

		private readonly IList rings = new ArrayList();

		private Envelope totalEnv = new Envelope();

		private SweepLineIndex sweepLine;

		private Coordinate nestedPt;

		public class OverlapAction : ISweepLineOverlapAction
		{
			public bool IsNonNested
			{
				get
				{
					return this.isNonNested;
				}
			}

			public OverlapAction(SweeplineNestedRingTester container)
			{
				this.container = container;
			}

			public void Overlap(SweepLineInterval s0, SweepLineInterval s1)
			{
				ILinearRing linearRing = (ILinearRing)s0.Item;
				ILinearRing linearRing2 = (ILinearRing)s1.Item;
				if (linearRing == linearRing2)
				{
					return;
				}
				if (this.container.IsInside(linearRing, linearRing2))
				{
					this.isNonNested = false;
				}
			}

			private readonly SweeplineNestedRingTester container;

			private bool isNonNested = true;
		}
	}
}
